2016-12-29 3 views
2

Отказ от ответственности, я разработчик iOS, который работает с шифрованием на Android. Как бы то ни было, мне удалось добиться шифрования в Android, но я спрашиваю себя, как один модульный тест для шифрования и дешифрования данных?Модульное тестирование шифрования и дешифрования в Java

Теперь первая мысль, которая приходит на ум, будет что-то вроде:

String encryptedInputData = encryptedInputData("Hello"); 
String decryptedData = decryptData(encryptedInputData); 
Assert.assertEquals(decryptedData,"Hello"); 

Этот тест, однако позах один недостаток ... Если что-то сделал изменения в encryptedInputData и decryptData методов, этот тест будет не говорит, что изменилось и почему оно сейчас ломается. Поэтому я хотел бы написать гораздо более подробные тесты. Так, например, учитывая этот код:

Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding"); 
cipher.init(Cipher.ENCRYPT_MODE, key); 
byte[] data = cipher.doFinal(message); 

Я хотел бы, чтобы убедиться, что переменная cipher использует алгоритм RSA в режиме ECB без заполнения. Я хотел бы, чтобы проверить, что message в .doFinal(message) следует определенный формат и т.д.

Теперь я предположил бы, что я смог бы дразнить Cipher класс, проблема здесь заключается в том, что шифрование и дешифрование, что было написано, служит только в качестве класса Util и для того, чтобы иметь возможность тестировать это, мне нужно было бы передать код Cipher в код, который, учитывая, что это класс Util, кажется, что он будет запутанным, т.е. мне пришлось бы либо создать метод init только для целей единичного тестирования или создания методов настройки, чтобы проверить это. Который позволил бы мне модулировать код, но тогда класс Util становится неуклюжим с кодом, который мне действительно не нужен для производственных целей.

Есть ли какие-либо изящные способы модуляции тестовых сценариев, подобных этому? то есть encryptedInputData и decryptData являются общедоступными методами, но эти методы используют различные частные методы, которые, откровенно говоря, должны быть проверены на единицу, проблема тогда в том, как?

ответ

2

Настоящий ответ вам не нужно. Вы никогда не должны реализовывать свои собственные процедуры шифрования. Мало того, что вы, скорее всего, ошибаетесь, есть чрезвычайно сложные вещи, которые вам нужно сделать, чтобы убедиться, что на самом деле они не могут быть взломаны из-за проблем с реализацией (например, если одна ветвь оператора if занимает больше времени, чем другая , вы можете выяснить, какова ценность проверки). Вы всегда должны использовать открытую исходную, хорошо просматриваемую библиотеку.

Поскольку вы не реализуете его самостоятельно, вам не нужно его тестировать. Библиотечные писатели должны быть. Если вам это нравится, запустите свой тестовый пакет как часть своего собственного, но я бы подумал, что это пустая трата времени - они сделали это до выпуска, и вам действительно нужно всего лишь запустить его один раз.

0

Гейб прав в своем ответе о том, что он действительно действительно является консервативным при повторном изобретении колеса; особенно когда это колесо о криптографии/безопасности/... таких вещах. Скорее всего, вы ошибетесь. И хакеры любят людей, пытающихся прийти со своей «защищенной криптографией».

Но ответьте на фактический вопрос: попробуйте пойти с TDD (разработка, основанная на испытаниях). Понимаете, ваша проблема в том, что вы создали некоторые API, которые трудно тестировать.

Вы правы, вы хотите, чтобы это «от конца до конца», как тест, который гарантирует, что дешифрование (шифрование («что-то»)) происходит с «чем-то». Теперь ваша проблема: если вы только пишете свой код с учетом этих двух методов; то блок тестирование сложно.

Таким образом: с самого начала, когда вы считаете, «какие классы мне нужны»; и «какие методы входят в класс, на который вы должны сосредоточиться, и как мне это проверить».

Другими словами: это один из случаев, когда TDD является очень важным - потому что вы действительно хотите проектировать единицы, которые можно протестировать. И лучшая практика, чтобы получить там: сначала напишите свои тесты. Если вы проектируете свои устройства так, чтобы их можно было протестировать (потому что вы сначала написали тесты); сюрприз - их можно протестировать. Сделать их «проверяемыми» после того, как факт всегда громоздкий; и чаще всего: почти невозможно.

0

Насколько я вижу, Cipher находится в javax.cryptoclass. Поэтому вам не нужно издеваться над этим.

Вы можете написать модульные тесты, чтобы убедиться, что: 1. Key правильно сгенерирован и соответствует требованиям. 2. CipherInputStream успешно создан. 3. Копирование текста в файл и чтение его после дешифрования делает матч:

@Test 
public void streamEncryptionDecryptionTest() { 

    try { 
     File file = tempFolder.newFile("test.txt"); 

     String content = "This is the text content"; 
     System.out.println("Original content for file = " + content); 


     OutputStream fop = new FileOutputStream(file); 

     byte[] key = EncryptionHelper.createKey(); 

     fop = EncryptionHelper.getInstance(key).getEncryptedOutputStream(fop); 

     // if file doesn't exists, then create it 
     if (!file.exists()) { 
      file.createNewFile(); 
     } 

     // get the content in bytes 
     byte[] contentInBytes = content.getBytes(); 

     fop.write(contentInBytes); 
     fop.flush(); 
     fop.close(); 

     System.out.println("Encryption Done"); 

     { // Read content w/o decryption 
      InputStream fis = new FileInputStream(file); 
      System.out.println("Content w/o decryption"); 

      int contentChars; 
      while ((contentChars = fis.read()) != -1) { 
       // convert to char and display it 
       System.out.print((char) contentChars); 
      } 

     } 

     { // Decrypted content 
      InputStream fis = new FileInputStream(file); 
      fis = EncryptionHelper.getInstance(key).getDecryptedInputStream(fis); 

      System.out.println("Total file size to read (in bytes) : " 
        + fis.available()); 

      System.out.println("Decrypted content"); 

      int contentChars; 
      while ((contentChars = fis.read()) != -1) { 
       // convert to char and display it 
       System.out.print((char) contentChars); 
      } 
     } 


    } catch (IOException e) { 
     e.printStackTrace(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
     Assert.assertTrue("security exception", false); 
    } 
} 

Хотя этот тест не имеет явную проверку Assertion, вы можете добавить:

for (int i = 0; i < buffer.length; i++) { 
    byte b = buffer[i]; 
    System.out.print(b); 
    decryptedContent[i] = b; 
} 

, а затем проверить массивы:

Assert.assertArrayEquals(bytesEncoded, decryptedContent); 

Имейте в виду, что вы не должны сравнивать байтовые массивы, преобразовывая их в строку, так как это даст вам неправильную реализацию.

  1. Правильно работает шифрование и дешифрование частичного буфера. В зависимости от ваших потребностей.