Ускорение AES для Java

Корутинги должны иметь возможность

  1. запускать
  2. регулировать выход для вызывающего абонента (необязательно производить некоторые промежуточные результаты)
  3. иметь возможность получить некоторую информацию от вызывающего абонента и резюме

Итак, вот небольшая демонстрация асинхронных функций (ака родных сопрограмм), которые делают это без использования asyncio или любых других модулей / фреймворков, которые обеспечивают цикл событий. Требуется хотя бы python 3.5. См. Комментарии внутри кода.

#!/usr/bin/env python

import types

# two simple async functions
async def outer_af(x):
    print("- start outer_af({})".format(x))
    val = await inner_af(x)  # Normal way to call native coroutine.
                             # Without `await` keyword it wouldn't
                             # actually start
    print("- inner_af result: {}".format(val))
    return "outer_af_result"


async def inner_af(x):
    print("-- start inner_af({})".format(x))
    val = await receiver()  # 'await' can be used not only with native
                            # coroutines, but also with `generator-based`
                            # coroutines!
    print("-- received val {}".format(val))
    return "inner_af_result"


# To yiled execution control to caller it's necessary to use
# 'generator-based' coroutine: the one created with types.coroutine
# decorator
@types.coroutine
def receiver():
    print("--- start receiver")
    # suspend execution / yield control / communicate with caller
    r = yield "value request"
    print("--- receiver received {}".format(r))
    return r

def main():
    # We want to call 'outer_af' async function (aka native coroutine)
    # 'await' keyword can't be used here!
    # It can only be used inside another async function.
    print("*** test started")
    c = outer_af(42)  # just prepare coroutine object. It's not running yet.
    print("*** c is {}".format(c))

    # To start coroutine execution call 'send' method.
    w = c.send(None)  # The first call must have argument None

    # Execution of coroutine is now suspended. Execution point is on
    # the 'yield' statement inside the 'receiver' coroutine.
    # It is waiting for another 'send' method to continue.
    # The yielded value can give us a hint about what exectly coroutine
    # expects to receive from us.
    print("*** w = {}".format(w))

    # After next 'send' the coroutines execution would finish.
    # Even though the native coroutine object is not iterable it will
    # throw StopIteration exception on exit!
    try:
        w = c.send(25)
        # w here would not get any value. This is unreachable.
    except StopIteration as e:
        print("*** outer_af finished. It returned: {}".format(e.value))


if __name__ == '__main__':
    main()

Вывод выглядит так:

*** test started
*** c is <coroutine object outer_af at 0x7f4879188620>
- start outer_af(42)
-- start inner_af(42)
--- start receiver
*** w = value request
--- receiver received 25
-- received val 25
- inner_af result: inner_af_result
*** outer_af finished. It returned: outer_af_result

Дополнительный комментарий. Похоже, что невозможно получить контроль изнутри собственной сопрограммы. yield не разрешено внутри функций async! Поэтому необходимо import types и использовать декоратор coroutine. Это черная магия! Честно говоря, я не понимаю, почему yield запрещен, поэтому требуется сборка сопрограмм на основе родных и генераторов.

17
задан Chris Lercher 15 June 2010 в 13:22
поделиться

4 ответа

Сама по себе JVM не будет использовать преимущества специальных функций ЦП при выполнении кода, который является шифрованием AES: распознавание некоторого кода как реализации AES выходит за рамки возможностей JIT-компилятора. Чтобы использовать специальное оборудование (например, «Замок» на процессорах VIA или инструкции AES-NI на новых процессорах Intel), вы должны в какой-то момент пройти через «собственный код».

Возможно, провайдер JCE может сделать это за вас. Я не знаю ни одного легкодоступного поставщика JCE, который включает в себя оптимизированный собственный код для AES (был проект под названием Apache JuiCE , но, похоже, он остановился, и я не знаю его статуса). Однако вполне возможно, что SunJCE сделает это в будущей версии (но с учетом того, что Oracle покупает Sun и слишком много возможностей OpenJDK 7, неясно, когда будет выпущена следующая версия Java). В качестве альтернативы вы можете использовать собственный код самостоятельно. Собственный код вызывается через JNI , а для собственного кода AES популярной реализацией является реализация Брайана Гладмана . Когда вы получаете более крупный и новый процессор с инструкцией AES-NI, замените этот собственный код некоторым кодом, который знает об этих инструкциях, как Intel описывает .

Используя AES-128 вместо AES-256, вы должны получить прирост скорости на + 40%. Взлом AES-128 в настоящее время находится за пределами технологической досягаемости человечества и останется таковой в течение следующих нескольких десятилетий.Вам действительно нужен 256-битный ключ для AES?

14
ответ дан 30 November 2019 в 11:51
поделиться

Обычно шагом, который использует больше времени, является Инициирование KeyGenerator.

KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256); // This step takes more time
KeyGenerator aesKey = keyGen.generateKey();

способ, которым я решил его, путем генерации пула KeyGenerator экземпляры перед сервером statup и многократного использования их для только для Генерации ключей

0
ответ дан 30 November 2019 в 11:51
поделиться

Я бы также посоветовал использовать AES-128, а не 256. Если код слабо связан и все еще существует, сколько бы лет ни потребовалось для того, чтобы AES-128 стал архаичным, я предполагаю, что его будет намного проще обновить шифрование в этот момент (когда оборудование станет более мощным), чем пытаться оптимизировать производительность с помощью оборудования сейчас.

Конечно, предполагается, что он слабосвязанный: D

1
ответ дан 30 November 2019 в 11:51
поделиться

Простой поиск в Google выявит несколько поставщиков JCE, которые заявляют об аппаратном ускорении Solaris Crypto Framework. Я слышал, что точка безубыточности составляет 4K (где меньше 4k быстрее выполнять, используя JVM java-провайдеры).

Я мог бы посмотреть на использование реализации NSS, она может иметь некоторые оптимизации компилятора для вашей платформы (и вы, конечно, можете собирать из исходников с их включением); хотя я сам не использовал ее. Большим преимуществом аппаратного провайдера, вероятно, является тот факт, что ключи могут храниться в аппаратном обеспечении таким образом, что их можно использовать, не раскрывая их для ОС.

Обновление: Я должен упомянуть, что в исходнике Keyczar есть полезные сведения (где-то в исходнике или в сопутствующих документах) о снижении накладных расходов на инициализацию шифра. Он также делает именно то, что вы хотите (см. Encrypter), и, похоже, реализует асинхронное шифрование (используя пул потоков).

4
ответ дан 30 November 2019 в 11:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: