2017-01-30 11 views
0

У меня есть приложение, которое должно запускать плагины, написанные той же компанией, но обнаруженные во время выполнения.Как аутентифицировать, что плагиновая банка была написана одной компанией?

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

Что такое простой способ выполнить эту проверку подлинности?

Достаточно ли разумно пройти тест-ответ, или мне нужно подписать плагин?

Если мне нужно подписать плагин, какие API-интерфейсы я буду использовать для аутентификации?

+0

Вы управляете подключаемым механизмом? –

+0

Поскольку он имеет дело с Jars, для Maven или Gradle для ваших зависимостей сборки/управления jar достаточно, поскольку вы можете указать имя, автора и т. Д. – SomeStudent

+0

@ ThorbjørnRavnAndersen - Да, полностью. В идеале он будет равен нулю или немногим зависимостям, кроме стандартной библиотеки Java SE. –

ответ

0

Это ответ, который я получил после чтения и экспериментирования.

В этом случае может быть достаточно self-signed certificate, так как никакой сторонний код не должен аутентифицироваться. Код хостинга может использовать открытый ключ для проверки подключаемого модуля.

Подробности

Приведенные ниже примеры использования алгоритма по умолчанию ключ. Вы можете указать более безопасный алгоритм с -keyalg.

Сделать хранилище ключей, публичный/пару закрытый ключ и самоподписанный сертификат, содержащий открытый ключ

keytool -genkeypair -alias myalias -validity 365 -keystore mykeystore 

Действительность измеряется в днях.

Экспорт сертификат, содержащий открытый ключ

keytool -export -keystore mykeystore -alias myalias -file mycertificate.cer 

Во время сборки, подписать плагин банку

jarsigner -keystore mykeystore -signedjar my_signed.jar my_unsigned.jar myalias 

Во время выполнения аутентификации плагин банку содержание

Этот т est harness можно использовать для тестирования следующего кода.

public class CEVerify { 
    public static void main(String[] args) throws IOException, CertificateException { 
    File jarFile = new File("C:\\myplugins\\my_signed.jar"); 
    String certificatePath = "C:\\mycertificates\\mycertificate.cer"; 

    File certificateFile = new File(certificatePath); 

    PublicKey publicKey = getPublicKeyFromCertificate(certificateFile); 

    JarFile jar = new JarFile(jarFile); 
    boolean isVerified = verify(jar, publicKey); 
    if (isVerified) { 
     System.out.println("Verified!"); 
    } 
    else { 
     System.err.println("NOT verified!"); 
    } 

    } 

Вы можете извлечь открытый ключ из сертификата, как это:

private static PublicKey 
    getPublicKeyFromCertificate(File certificateFile) 
    throws CertificateException, FileNotFoundException 
    { 
     CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); 

     FileInputStream inCertificate = new FileInputStream(certificateFile); 
     Certificate certificate = certificateFactory.generateCertificate(inCertificate); 
     return certificate.getPublicKey(); 
    } 

Учитывая баночка файл и открытый ключ, вы можете проверить соответствующие записи в банке. Возможно, вам придется исключить другие файлы, если вы использовали другой -keyalg, например RSA.

private static boolean 
    verify(JarFile jar, PublicKey publicKey) throws IOException { 
     Enumeration<JarEntry> jarEntries = jar.entries(); 
     while (jarEntries.hasMoreElements()) { 
     JarEntry jarEntry = jarEntries.nextElement(); 

     if (jarEntry.isDirectory()) { 
      continue; 
     } 
     else { 
      String entryName = jarEntry.getName(); 
      if (entryName.endsWith(".SF") || entryName.endsWith(".DSA")) { 
       continue; 
      } 
      else if (! verifyJarEntry(jar, publicKey, jarEntry)) { 
       return false; 
      } 
     } 
     } 

     return true; 
    } 

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

private static boolean 
    verifyJarEntry(JarFile jar, PublicKey publicKey, JarEntry jarEntry) 
    throws IOException 
    { 
     try { 
      InputStream in = jar.getInputStream(jarEntry); 
      readAllOf(in); 

      // public Certificate[] getCertificates() 
      // ... This method can only be called once the JarEntry has been 
      // completely verified by reading from the entry input stream 
      // until the end of the stream has been reached. Otherwise, this 
      // method will return null. 

      Certificate[] certificates = jarEntry.getCertificates(); 
      if ((null == certificates) || (0 == certificates.length)) { 
       return false; 
      } else { 
       for (int i = 0; i < certificates.length; ++i) { 
        Certificate certificate = certificates[i]; 
        try { 
         certificate.verify(publicKey); 
         return true; 
        } catch (Exception e) { 
         continue; 
        } 
       } 
       return false; 
      } 
     } catch (SecurityException e) { 
      return false; 
     } 
    } 

Наконец, это метод, названный выше, чтобы прочитать все байты в записи в банке.

private static void readAllOf(InputStream in) throws IOException { 
     byte[] buffer = new byte[4096]; 
     while (0 < in.read(buffer)) { 
      continue; 
     } 
    } 

 Смежные вопросы

  • Нет связанных вопросов^_^